namespace hjc {

	export class Notifier extends Singleton {

		private $ntfMap: Map<string, NotifyOptions[]> = new Map();

		public attach(type: string, notified: Function, observer?: any, view?: egret.DisplayObject): void {
			if (isFunc(notified)) {
				let arr = this.$ntfMap.get(type);
				if (isArray(arr)) arr.push({ notified, observer, view });
				else this.$ntfMap.set(type, [{ notified, observer, view }]);
			} else hjc.error('notified attached must be a function ...');
		}

		public detach(type: string, notified: Function, observer?: any): void {
			if (isFunc(notified)) {
				let arr = this.$ntfMap.get(type);
				if (notEmptyArr(arr)) {
					for (let i = 0; i < arr.length; i++) {
						let tNotified = arr[i];
						let bingo = (!!observer && tNotified.observer === observer && tNotified.notified === notified) || (!observer && tNotified.notified === notified);
						if (!bingo) continue;
						arr.splice(i, 1); i--;
					}
				}
			} else hjc.error('notified dettached must be a function ...');
		}


		public dispatch(type: string, data?: any, source?: any): void {
			let arr = this.$ntfMap.get(type);
			if (notEmptyArr(arr)) {
				let ntf = game.claim(Notification, type, data, source)
				arr.forEach((options: NotifyOptions) => {
					if (!!options.view && !options.view.parent) return;
					utils.call(options.notified, options.observer, ntf);
				});
			}
		}
	}

	type NotifyOptions = {
		notified: Function,
		observer?: any,
		view?: egret.DisplayObject,
	}
}

